import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min';

export default class BaseFrame {
	constructor() {
		this._loop = null;
		this.dom = null;
		this._width = 400;
		this._height = 300;
		this._init();
	}
	_init() {
		this._initCamera();
		this._initScene();
		this._initRenderer();
		this._initControls();
		this._initClock();
		this._initGui();
		this._initGround();
	}
	_initCamera() {
		this.camera = new THREE.PerspectiveCamera(60, this._width / this._height, 0.01, 1000);
		this.camera.position.set(0, 0, 6);
	}
	_initScene() {
		this.scene = new THREE.Scene();
	}
	_initRenderer() {
		this.renderer = new THREE.WebGLRenderer({ antialias: true, transparent: true });
		this.renderer.setSize(this._width, this._height);
		this.renderer.setPixelRatio(window.devicePixelRatio);
	}
	_initControls() {
		this.controls = new OrbitControls(this.camera, this.renderer.domElement);
	}
	_initClock() {
		this.clock = new THREE.Clock();
	}
	_initGui() {
		this.gui = new GUI();
		this.gui.close();
	}
	_initGround() {
		let groundGeom = new THREE.PlaneGeometry(10, 10);
		let groundMate = new THREE.MeshBasicMaterial({
			map: new THREE.TextureLoader().load('/img/views/ground.png'),
			transparent: true,
			color: new THREE.Color(0x46c2f7),
			alphaMap: new THREE.TextureLoader().load('/img/views/ground2.png'),
			side: THREE.DoubleSide,
		});
		this.groundMesh = new THREE.Mesh(groundGeom, groundMate);
		this.groundMesh.rotation.x = -Math.PI / 2;
		this.scene.add(this.groundMesh);
	}
	renderOnce() {
		this.update();
		this.controls.update();
		this.renderer.render(this.scene, this.camera);
	}
	play() {
		this.clock.start();
		this.animate();
	}
	stop() {
		cancelAnimationFrame(this._loop);
	}
	animate() {
		this._loop = requestAnimationFrame(this.animate.bind(this));
		this.renderer.render(this.scene, this.camera);
		this.controls.update();
		this.update();
	}
	appendToBox(dom) {
		this.dom = dom;
		this.resize();
		this.dom.appendChild(this.renderer.domElement);
		this.dom.appendChild(this.gui.domElement);
	}
	resize() {
		this._width = this.dom.offsetWidth;
		this._height = this.dom.offsetHeight;
		this.renderer.setSize(this._width, this._height);
		this.camera.aspect = this._width / this._height;
		this.camera.updateProjectionMatrix();
		this.renderOnce();
	}
	update() {}
}
